package com.dtm.client;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream.PutField;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Vector;

import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.os.Handler;
import android.os.Vibrator;
import android.util.Log;

import com.dtm.client.thread.EndGameListener;
import com.dtm.client.thread.UpdateListListener;
import com.dtm.client.thread.UpdateStatusListener;
import com.dtm.server.ClientThread;
import com.dtm.ui.InRoomActivity;
import com.dtm.ui.MainActivity;

public class ClientConnectedThread implements Runnable, UpdateStatusListener{

	public static final int CONNECTED = 1;
	public static final int READY = 2;
	public static final int HOST = 3;

	public static final int REG = 0;
	public static final int UDL = 1;
	public static final int STR = 2;
	public static final int GAME_START = 3;
	public static final int LIST = 4;
	public static final int UPDATE_STATUS = 5;
	public static final int SERVER_ACCEPT = 6;
	public static final int SERVER_REFUSE = 7;
	public static final int GAME_END = 8;
	
	public static final int GAME_IN_WAITING = 0;
	public static final int GAME_IN_PROGRESS = 1;
	
	private Socket socket;
	private ArrayList<Client> clients = new ArrayList<Client>();
	private DataInputStream inputStream;
	private DataOutputStream outputStream;
	private String serverIP;
	private int port;
	private Client client;
	private int clientStatus;
	
	private static int gameStatus = ClientConnectedThread.GAME_IN_WAITING;
	
	private EndGameListener endGameListener;
	private UpdateListListener updateList;
	private Handler handler;
	private String messageData;
	private Context context;
	private String messageFromServer;

	public ClientConnectedThread(String serverIP, int port, UpdateListListener updateList, Handler handler, Context context, EndGameListener endGameListener) {
		this.serverIP = serverIP;
		this.port = port;
		this.updateList = updateList;
		this.handler = handler;
		this.context = context;
		this.endGameListener = endGameListener;
	}

	@Override
	public void run() {
		try {
			InetAddress serverAddr = InetAddress.getByName(serverIP);
			socket = new Socket(serverAddr, port);
			inputStream = new DataInputStream(socket.getInputStream());
			outputStream = new DataOutputStream(socket.getOutputStream());
			sendReg();
			
			clientStatus = ClientConnectedThread.CONNECTED;
			SensorThread sensorThread = new SensorThread(context);
			sensorThread.setUpdateStatus(this);
			sensorThread.start();
			
			while(!socket.isClosed()) {
				messageFromServer = inputStream.readUTF();
				int typeCode = ConvertPackge.getCode(messageFromServer);
				messageData = ConvertPackge.getJsonData(messageFromServer);
				
				switch(typeCode) {
				case ClientConnectedThread.UDL :
					listUpdate();
					break;
				case ClientConnectedThread.GAME_START :
					Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
					long[] pattern = new long[]{0, 300};
					vibrator.vibrate(pattern, -1);
					gameStatus = ClientConnectedThread.GAME_IN_PROGRESS;
					Log.e("clientConnectedThread", "GAMESTART");
					break;
				case ClientConnectedThread.GAME_END :
					gameStatus = ClientConnectedThread.GAME_END;
					handler.post(new Runnable() {
						
						@Override
						public void run() {
							endGameListener.onEndGame(ConvertPackge.getJsonData(messageFromServer));
						}
					});
					break;
				}
				
			}

		} catch (UnknownHostException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}
	
	private void listUpdate() {
		final Vector<Client> clientVector = ConvertPackge.jsonToVector(messageData);
		handler.post(new Runnable() {
			
			@Override
			public void run() {
				updateList.onListChange(clientVector);
			}
		});
	}
	
	private void updateStatus() {
		try {
			outputStream.writeUTF("" + UPDATE_STATUS + clientStatus);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void updateLoserName(String loserName) {
		try {
			outputStream.writeUTF("" + ClientConnectedThread.GAME_END + loserName);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void sendReg() {
		client = new Client(MainActivity.userName, ClientConnectedThread.CONNECTED, MainActivity.userAvatar);
		try {
			outputStream.writeUTF(ConvertPackge.convertToJon(client, ClientConnectedThread.REG));
			outputStream.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void onUpdateStatus(int status) {
		if (status == SensorThread.FACE_DOWN) {
			clientStatus = ClientConnectedThread.READY;
			updateStatus();
		} else if(status == SensorThread.FACE_UP) {
			if (gameStatus == ClientConnectedThread.GAME_IN_PROGRESS) {
				updateLoserName(client.getName() + " losed");
			}
			clientStatus = ClientConnectedThread.CONNECTED;
			updateStatus();
		}
		
	}

}
